package com.mattgarner.jaddas.cli;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.mattgarner.jaddas.cli.data.BulkLoader;
import com.mattgarner.jaddas.cli.data.BulkLoaderException;
import com.mattgarner.jaddas.cli.net.Client;
import com.mattgarner.jaddas.cli.net.Message;
import com.mattgarner.jaddas.cli.net.Protocol;
import com.mattgarner.jaddas.common.ResultSet;
import com.mattgarner.jaddas.common.ResultSetException;
import com.mattgarner.jaddas.common.ResultSetHeader;

public class CommandParser {
	private Client client;
	private ClientConfigurationManager clientConfig;
	private String commandBuffer = "";
	
	public CommandParser() {
		client = Client.getInstance();
		clientConfig = ClientConfigurationManager.getInstance();
	}
	
	public final void parseConsoleInput(String consoleInput) {
		final String[] remoteCommands = {"SET", "SHOW", "SELECT", "INSERT", "CREATE", "DROP", "ALTER"};
		boolean cmdMatch = false;
		
		if(consoleInput.matches(".*;\\s*$")) {
			commandBuffer += " " + consoleInput;
			commandBuffer = commandBuffer.replaceAll("^\\s*", "");
			
			for(int a = 0; a<remoteCommands.length; a++) {
				
				// parse remote commands
				if(commandBuffer.toUpperCase().matches("^"+remoteCommands[a]+" .*")) {
					client.sendMessage(new Message(Protocol.MSG_COMMAND, commandBuffer));
					
					byte replyFlag = 127;
					while((replyFlag != Protocol.MSG_OK) && (replyFlag != Protocol.MSG_NAK)) {
						Message msgReply = client.readMessage();
						replyFlag = msgReply.getMessageFlag();
						
						if(replyFlag == Protocol.MSG_RESULTSET_HEADER) {
							try { 
								ResultSetHeader rsHeader = new ResultSetHeader(clientConfig.getStringEncoding(), msgReply.getMessageBytes());
								Message msgResultSet = client.readMessage();
								if(msgResultSet.getMessageFlag() == Protocol.MSG_RESULTSET_ROW) {
									ResultSet resultSet = new ResultSet(rsHeader, msgResultSet.getMessageBytes());
									System.out.print(resultSet.toFormattedString());
								} 
							} catch (ResultSetException e) {
								System.out.println("ResultSetException: " + e.getMessage());
							}
						} 
						
						if(replyFlag == Protocol.MSG_OK) {
							System.out.println("<< OK: " + msgReply.getMessageString());
						} 
						if(replyFlag == Protocol.MSG_NAK) {
							System.out.println("<< ERR: " + msgReply.getMessageString());
						}
					}
					cmdMatch = true;
					break;
				}
			}

			// parse local commands
			if(!cmdMatch) {
				if(commandBuffer.toUpperCase().matches("^IMPORT INTO .*")) {
					
					//IMPORT INTO census.dsTest4 FROM FILE "c:/tmp/sample.csv.txt";
					String[] cmd = extractRegexGroups("(?i)^IMPORT\\s+INTO\\s+([A-Z0-9_\\.]*?)\\s+(.*?)\\s*;$", commandBuffer);

					String dsName = null;
					String args = null;
					try {
						dsName = cmd[0];
						args = cmd[1];
					} catch (Exception e) {
						System.out.println("<< ERR: Invalid arguments.");
					}

					BulkLoader bulkLoader = new BulkLoader();					
					bulkLoader.setTargetTable(dsName);
					
					// strip FROM FILE argument
					String[] fromFileArgs = extractRegexGroups("(?i)FROM FILE ((\"(.*?)\")|([^\\s]+))\\s*", args);
					String fileName = null;
					try {
						fileName = fromFileArgs[0].replaceAll("\"", "");
					} catch (Exception e) {
						System.out.println("<< ERR: Invalid arguments.");
					}					
					bulkLoader.setInputFileName(fileName);

					System.out.println(">> OK: Beginning import.");
					try {
						bulkLoader.doBulkImport(client);
					} catch (BulkLoaderException e) {
						System.out.println("<< ERR: " + e.getMessage());
					}
					
					cmdMatch = true;
				}
			}			
			
			
			if((commandBuffer.toUpperCase().matches("^EXIT;$")) || (commandBuffer.toUpperCase().matches("^QUIT;$"))) {
				System.exit(0);
			}
			
			if(!cmdMatch) {
				System.out.println("<< ERR: Unrecognized command.");
			}
			
			commandBuffer = "";
			// print console prompt
			System.out.print("cli> ");
		} else {
			System.out.print("---> ");
			commandBuffer += " " + consoleInput;
		}
		
		
	}
	
	public String[] extractRegexGroups(String regex, String inputString) {
		Pattern p;
		Matcher m;
		try { 
			p = Pattern.compile(regex);
			m = p.matcher(inputString);
			m.find();
			String[] output = new String[m.groupCount()];
			for(int a = 0; a<m.groupCount(); a++) {
				output[a] = m.group(a+1);
			}
			return output;
		} catch(IllegalStateException e) {
			String[] output = new String[16];
			for(int b=0; b<output.length; b++) { 
				output[b] = "";
			}
			return output;
		}
	}
}
